package com.zh.filetransport.chat

import com.zh.filetransport.model.DATA_KB
import org.tinylog.Logger
import java.io.IOException
import java.net.InetSocketAddress
import java.nio.ByteBuffer
import java.nio.channels.ClosedChannelException
import java.nio.channels.DatagramChannel
import java.nio.charset.StandardCharsets
import kotlin.concurrent.thread

/**
 *
 * @author Zhou
 * @date 17:54 2025/5/31
 */
private val log = Logger.tag("ChatServiceKt")

private lateinit var chatService: ChatService

fun GetChatService() = chatService

fun CreateChatService(port: Int): ChatService {
    chatService = ChatService(port)
    return chatService
}

class ChatService(val serverPort: Int) {
    private val buffer = ByteBuffer.allocate(DATA_KB)
    private var channel: DatagramChannel

    init {
        //获取通道
        channel = DatagramChannel.open()
        channel.configureBlocking(true) //设为阻塞
    }

    private fun setupSocketListeners(callback: (Pair<String, String>) -> Unit) {
        while (true) {
            try {
                val sender = channel.receive(buffer) as? InetSocketAddress ?: return
                buffer.flip()
                val message = String(buffer.array(), 0, buffer.remaining(), Charsets.UTF_8)
                buffer.clear()

                callback(message to sender.address.hostAddress)
            } catch (e: ClosedChannelException) {
                log.debug("closed chat udp channel ...", "")
                break
            } catch (e: IOException) {
                e.printStackTrace()
            }
        }
    }

    /**
     * 发送消息
     */
    fun chatSend(message: String, remoteIp: String): Boolean {
//        println("call chatSend to $remoteIp messsage: $message")
        if (remoteIp.isEmpty() || message.isEmpty()) {
            log.info("发送消息失败。remoteIp 或 message 不能为空", "")
            return false
        }
        val msgBuffer = ByteBuffer.wrap(message.toByteArray(StandardCharsets.UTF_8))
        try {
            //发送数据
            channel.send(msgBuffer, InetSocketAddress(remoteIp, serverPort))
            return true
        } catch (ex: Exception) {
            log.error("发送消息出现异常。 " + ex.message, "")
            return false
        } finally {
            msgBuffer.clear()
        }
    }

    /**
     * 启动服务
     */
    fun start(callback: (Pair<String, String>) -> Unit) {
        //绑定本地端口
        channel.bind(InetSocketAddress(serverPort)).apply {
            log.info("ChatService 已启动... 监听端口 $serverPort","")
        }

        thread {
            setupSocketListeners(callback)
        }
    }

    /**
     * 关闭服务
     */
    fun shutdown() {
        channel.close().apply {
            log.info("ChatService 已停止","")
        }
    }
}